﻿/////////////////// Microsoft Windows PowerShell SnapIn ///////////////////////
//
// Filename:    Program.cs
//
// Developer:   Jonathan Tigner
//
// Description: Test Console app for Get-ItemMetadata SnapIn.
//
// Copyright (c) 2008, Jonathan Tigner
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.IO;
using System.Text;
using Shell32;

namespace MExCon
{
    class Program
    {
        string[] path = {System.Reflection.Assembly.GetExecutingAssembly().Location};
        
        [STAThread]
        static void Main(string[] args)
        {
            Program p = new Program();
            p.InitArgs(p.path);
            p.BeginProcessing();
            p.ProcessRecord();

            Console.Read();
        }

        
        protected void InitArgs(string[] args)
        {
            path = args;
        }

        protected bool IsFile(FileSystemInfo fsi)
        {
            if ((fsi.Attributes & FileAttributes.Directory) == 0)
            {
                return true;
            }
            else return false;
        }

        protected bool IsDirectory(FileSystemInfo fsi)
        {
            if ((fsi.Attributes & FileAttributes.Directory) != 0)
            {
                return true;
            }
            else return false;
        }
        //Create instance of Windows Explorer shell
        Shell shell = new Shell();


        //Generate file system metadata properties dictionary
        protected Dictionary<string, int> InitializeProperties()
        {
            var current = Directory.GetDirectoryRoot("C:\\");
            Console.WriteLine("**Current Directory**: " + current);
            var directory = shell.NameSpace(current);
            Console.WriteLine("**Shell Namespace**: " + directory);
            var file = directory.Items().Item(Directory.GetFiles(current)[0]);
            Console.WriteLine("**Current File**: " + file);
            var props = new Dictionary<string, int>();

            for (int i = 0; i < int.MaxValue; i++)
            {

                var p = directory.GetDetailsOf(file, i);

                if (!String.IsNullOrEmpty(p) && !props.ContainsKey(p))
                {
                    props.Add(p, i);
                }
                else break;
            }
            return props;
        }

        Dictionary<string, int> itemProperties = new Dictionary<string, int>();

        public void BeginProcessing()
        {
            Console.WriteLine("Initializing Properties:");
            Console.WriteLine("");
            itemProperties = InitializeProperties();
            Console.WriteLine("Properties:");
            int i = 0;
            foreach (var s in itemProperties.Keys)
            {
                itemProperties.TryGetValue(s, out i);
                Console.WriteLine(i + ": " + s);
            }
            Console.WriteLine("Total Properties: " + itemProperties.Count);
        }        

        public void ProcessRecord()
        {
            Console.WriteLine("Paths: ");

            foreach (var item in path)
            {
                Console.WriteLine(item);
                var fsi = new DirectoryInfo(item);
                FolderItem fsItem;
                Folder directory;

                if (fsi != null)
                {
                    //Check if item is a directory
                    if (IsDirectory(fsi) && fsi.Exists)
                    {
                        Console.WriteLine("Item is a directory");
                        Console.WriteLine("");
                        //Check if path is a root location
                        if (fsi.Parent == null)
                        {
                            //Set Explorer shell namespace to root directory
                            directory = shell.NameSpace(fsi.FullName);
                            directory = directory.ParentFolder;

                            //Get file system item for given path
                            fsItem = directory.Items().Item(fsi.Name);
                            Console.WriteLine("**Current FileItem**: " + fsItem.Path);
                        }
                        else
                        {
                            //Set Explorer shell namespace to parent directory
                            directory = shell.NameSpace(fsi.Parent.FullName);
                            Console.WriteLine("**Shell Namespace**: " + directory.Title);

                            //Get file system item for given path
                            fsItem = directory.Items().Item(fsi.Name);
                            Console.WriteLine("**Current FileItem**: " + fsItem.Path);
                        }
                        
                        /* //Create PSObject
                        var psObj = new PSObject();

                        //Add custom type information
                        psObj.TypeNames[0] = "Custom.IO.File.Metadata";
                        psObj.Members.Add(new PSNoteProperty("Path", fsi.FullName));
                        */
                        //Add extended metadata
                        int i = 0;
                        Console.WriteLine("Writing item metadata:");
                        foreach (var key in itemProperties.Keys)
                        {
                                //Get integer value of current key and set i to that value
                                itemProperties.TryGetValue(key, out i);

                                //Get metadata for current file system item property
                                var itemProperty = directory.GetDetailsOf(fsItem,itemProperties[key]);
                            if(!String.IsNullOrEmpty(itemProperty))
                            {
                                Console.WriteLine(key + ": " + itemProperty);
                            }

                                /*  //Add NoteProperty corresponding to each metadata item
                                  if (psObj.Members.Match(key).Count == 0 && !String.IsNullOrEmpty(itemProperty))
                                  {
                                      Console.WriteLine("Adding NoteProperty: " + key + " = " + itemProperty);
                                      psObj.Members.Add(new PSNoteProperty(key, itemProperty));
                                  }*/
                                //Console.WriteLine("key: " + key + " i: " + i + " itemprop: " + itemProperties[key]);
                        }
                        //Console.WriteLine("");                        
                        Console.WriteLine("");
                        //WriteObject(psObj);
                    }
                    else if (IsFile(fsi))
                    {
                        var file = new FileInfo(item);
                        if (file.Exists)
                        {
                            Console.WriteLine("Item is a file");
                            Console.WriteLine("");
                            //Set Explorer shell namespace to directory
                            directory = shell.NameSpace(file.DirectoryName);
                            Console.WriteLine("**Current Directory**: " + directory.Title);

                            //Get file system item for given path
                            fsItem = directory.Items().Item(file.Name);
                            Console.WriteLine("**Current FileItem**: " + fsItem.Path);

                           /* //Create PSObject
                            var psObj = new PSObject();

                            //Add custom type information
                            psObj.TypeNames[0] = "Custom.IO.File.Metadata";
                            psObj.Members.Add(new PSNoteProperty("Path", file.FullName));
                            */
                            //Add extended metadata
                            int i = 0;
                            Console.WriteLine("Writing item metadata:");
                            foreach (var key in itemProperties.Keys)
                            {
                                //Get integer value of current key and set i to that value
                                itemProperties.TryGetValue(key, out i);

                                //Get metadata for current file system item property
                                var itemProperty = directory.GetDetailsOf(fsItem, itemProperties[key]);
                                if (!String.IsNullOrEmpty(itemProperty))
                                {
                                    Console.WriteLine(key + ": " + itemProperty);
                                }
                              /*  //Add NoteProperty corresponding to each metadata item
                                if (psObj.Members.Match(key).Count == 0 && !String.IsNullOrEmpty(itemProperty))
                                {
                                    Console.WriteLine("Adding NoteProperty: " + key + " = " + itemProperty);
                                    psObj.Members.Add(new PSNoteProperty(key, itemProperty));
                                }*/
                            }

                            //Console.WriteLine("");
                            //Console.WriteLine("Writing item metadata:");
                            //Console.WriteLine("");
                            
                            //WriteObject(psObj);
                        }
                        
                        //else
                        //{
                          //  WriteError(new ErrorRecord(new ArgumentException("Cannot find path because it does not exist", item), null, ErrorCategory.InvalidArgument, Path));
                        //}
                        Console.Read();
                    }
                }
            }
        }
    }
}
